package com.fingard.diagnostics;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;

import java.io.*;
import java.sql.Connection;
import java.util.Date;

public class LogHelper {
    /**
     * 异常堆栈输出到字符串
     */
    public static String getStackTrace(Throwable e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (pw != null) {
                pw.close();
            }
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        if (sw != null) {
            return sw.toString();
        }
        return "";
    }

    public static String getStackTraceFirstLine(Throwable e) {
        String str = getStackTrace(e).trim();
        int idx = str.indexOf("\n");
        if (idx > 0) {
            return str.substring(0, idx).trim();
        }
        return str;
    }


    public static String writeBankLog(int p_logID, Date p_sTime, Date p_eTime, String prefix, ReqRespHeader p_header, StringBuilder p_sbLog, boolean getLogFilePath) throws Exception {
        if ("Contract".equalsIgnoreCase(p_header.transType) || "QryContract".equalsIgnoreCase(p_header.transType)
                || "QryBatContract".equalsIgnoreCase(p_header.transType) || "UpContract".equalsIgnoreCase(p_header.transType)
                || "DeContract".equalsIgnoreCase(p_header.transType) || "QryDeContract".equalsIgnoreCase(p_header.transType)) {
            if (p_header.srcBankCode != null && p_header.srcBankCode.startsWith("FnGrd") && p_header.srcBankCode.length() == 8) {
                p_header.bankCode = p_header.srcBankCode;
            }
        }

        if (p_eTime == null) {
            p_eTime = new Date();
        }
        String tmpStrLogSeq = String.format("%04d", p_logID);
        String tmpSubFileName = "";
        if (FGBiz.enableAsyncBankLog) {//异步日志
            FGBiz.logTrace.infoNoTimeBank(p_header.bankCode, p_header.transType, p_sbLog.toString());
        } else {
            String tmpDateDir = Format.DateForLogFormat.format(p_eTime).replace("-", File.separator);

            String transTime = "";
            String traceID = "";
            if (StringHelper.hasAnyChar(p_header.logTransID) && StringHelper.hasAnyChar(p_header.bankCode)) {
                transTime = p_header.logTransID.split("_")[2];
                traceID = p_header.logTransID.split("_")[3];
                tmpDateDir = Format.DateForLogFormat.format(Format.DateTime14Format.parse(transTime)).replace("-", File.separator);
            }
            String reqSeqIDOrOwnAct = StringHelper.isNullOrEmpty(p_header.reqSeqID) ? p_header.ownAct : p_header.reqSeqID;
            reqSeqIDOrOwnAct = StringHelper.hasAnyChar(reqSeqIDOrOwnAct) ? (reqSeqIDOrOwnAct + "_") : "";
            reqSeqIDOrOwnAct = eleBillLogNameRule(p_header, reqSeqIDOrOwnAct);
            String transCommand = p_header.transType + "_" + p_header.bankCode;
            if (StringHelper.hasAnyChar(p_header.commandCode)) {
                transCommand = p_header.transType + "_" + p_header.commandCode + "_" + p_header.bankCode;
            }
            if (StringHelper.hasAnyChar(p_header.step)) {
                transCommand = p_header.transType + "_Step" + p_header.step + "_" + p_header.commandCode + "_" + p_header.bankCode;
            }
            if (StringHelper.hasAnyChar(transTime)) {
                if (StringHelper.isNullOrEmpty(prefix)) {
                    tmpSubFileName = FGBiz.dspCenter.bankLogsFirstDir + File.separator + tmpDateDir + File.separator + p_header.bankCode + File.separator + transCommand + "_" + reqSeqIDOrOwnAct + transTime + "_" + tmpStrLogSeq;
                } else {
                    tmpSubFileName = FGBiz.dspCenter.bankLogsFirstDir + File.separator + tmpDateDir + File.separator + p_header.bankCode + File.separator + transCommand + "_" + reqSeqIDOrOwnAct + prefix + "_" + transTime + "_" + tmpStrLogSeq;
                }
            } else {
                if (StringHelper.isNullOrEmpty(prefix)) {
                    tmpSubFileName = FGBiz.dspCenter.bankLogsFirstDir + File.separator + p_header.tenant + File.separator + tmpDateDir + File.separator + p_header.bankCode + File.separator + transCommand + "_" + reqSeqIDOrOwnAct + Format.DateTime14Format.format(p_eTime) + "_" + tmpStrLogSeq;
                } else {
                    tmpSubFileName = FGBiz.dspCenter.bankLogsFirstDir + File.separator + p_header.tenant + File.separator + tmpDateDir + File.separator + p_header.tenant + File.separator + p_header.bankCode + File.separator + transCommand + "_" + reqSeqIDOrOwnAct + prefix + "_" + Format.DateTime14Format.format(p_eTime) + "_" + tmpStrLogSeq;
                }
            }
            if (StringHelper.hasAnyChar(p_header.logTransID)) {
                tmpSubFileName = tmpSubFileName + "_" + traceID + ".txt";
            } else {
                tmpSubFileName = tmpSubFileName + "_" + ".txt";
            }
            String tmpLogFile = FGBiz.dspCenter.bankLogsDirPath + File.separator + tmpSubFileName;
            FileHelper.appendFile(tmpLogFile, p_sbLog.toString(), FGBiz.dspCenter.dspSet.charsetName);
        }

        if (FGBiz.dspCenter.enableDbLog && FGBiz.dspCenter.dbConnectionSet != null) {
            Connection dbConn = null;
            try {
                dbConn = FGBiz.dspCenter.dbConnectionSet.getConnection();
                String tableName = FGBiz.dspCenter.getLogTableName(p_header.getBusTime(p_sTime), dbConn);
                if (StringHelper.hasAnyChar(tableName)) {
                    /*"create table BANKLOGS"+tmpYearMonth+"(" +
                                    "  URID        VARCHAR2(24)," +
			        				"  BUSTIME   DATE," +
			        				"  BEGINTIME   DATE," +
			        				"  ENDTIME     DATE," +
			        				"  REQSEQID    VARCHAR2(32)," +
			        				"  TRANSSEQID  VARCHAR2(32)," +
			        				"  CREATETIME  DATE default sysdate not null," +
			        				"  BANKCODE    VARCHAR2(20)," +
			        				"  TRANSTYPE   VARCHAR2(20)," +
			        				"  COMMANDCODE VARCHAR2(20)," +
			        				"  DSPCODE     VARCHAR2(16)," +
			        				"  BANKFRONTCODE     VARCHAR2(20)," +
			        				"  CORPORATION VARCHAR2(32)," +
			        				"  ACTGROUP    VARCHAR2(32)," +
			        				"  LOGSUBFILE  VARCHAR2(128)," +
			        				"  LOGDATA     NCLOB)"*/
                    String sqlInsert = "insert into " + tableName + "(URID,BUSTIME,BEGINTIME,ENDTIME,REQSEQID,TRANSSEQID,BANKCODE,TRANSTYPE,COMMANDCODE,DSPCODE,BANKFRONTCODE,CORPORATION,ACTGROUP,LOGSUBFILE";
                    if (FGBiz.dspCenter.dbLogOnlySavePath == false) {
                        sqlInsert = sqlInsert + ",LOGDATA";
                    }
                    sqlInsert = sqlInsert + ")values(?,?,?,?,?,?,?,?,?,?,?,?,?,?";
                    Object[] paramters = new Object[14];
                    if (FGBiz.dspCenter.dbLogOnlySavePath == false) {
                        sqlInsert = sqlInsert + ",?";
                        paramters = new Object[15];
                    }
                    sqlInsert = sqlInsert + ")";
					/*
			        pre = dbConn.prepareStatement(sqlInsert);
			        pre.setString(1, Format.DateTime17Format.format(p_eTime)+tmpStrLogSeq);
			        pre.setTimestamp(2, new java.sql.Timestamp(p_header.getBusTime(p_sTime).getTime()));
			        pre.setTimestamp(3, new java.sql.Timestamp(p_sTime.getTime()));
			        pre.setTimestamp(4, new java.sql.Timestamp(p_eTime.getTime()));
			        pre.setString(5, p_header.reqSeqID);
			        pre.setString(6, p_header.transSeqID);
			        pre.setString(7, p_header.bankCode);
			        pre.setString(8, p_header.transType);
			        pre.setString(9, p_header.commandCode);
			        pre.setString(10, FGBiz.dspCenter.dspCode);
			        pre.setString(11, p_header.bankFrontCode);
			        pre.setString(12, p_header.corporation);
			        pre.setString(13, p_header.group);
			        pre.setString(14, tmpSubFileName);
			        StringReader strReader = null;
			        if(FGBiz.dspCenter.dbLogOnlySavePath == false){
			        	strReader = new StringReader(p_sbLog.toString());
			        	pre.setCharacterStream(15, strReader);
			        }
			        pre.execute();
			        */
                    paramters[0] = Format.DateTime17Format.format(p_eTime) + tmpStrLogSeq;
                    paramters[1] = new java.sql.Timestamp(p_header.getBusTime(p_sTime).getTime());
                    paramters[2] = new java.sql.Timestamp(p_sTime.getTime());
                    paramters[3] = new java.sql.Timestamp(p_eTime.getTime());
                    paramters[4] = p_header.reqSeqID;
                    paramters[5] = p_header.transSeqID;
                    paramters[6] = p_header.bankCode;
                    paramters[7] = p_header.transType;
                    paramters[8] = p_header.commandCode;
                    paramters[9] = FGBiz.dspCenter.dspCode;
                    paramters[10] = p_header.bankFrontCode;
                    paramters[11] = p_header.corporation;
                    paramters[12] = p_header.group;
                    paramters[13] = tmpSubFileName;
                    StringReader strReader = null;
                    if (FGBiz.dspCenter.dbLogOnlySavePath == false) {
                        strReader = new StringReader(p_sbLog.toString());
                        paramters[14] = strReader;
                    }
                    JDBCHelper.update(dbConn, sqlInsert, paramters);
                    if (strReader != null) {
                        strReader.close();
                    }
                } else {
                    System.out.println("取日志表失败");
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                if (dbConn != null) {
                    dbConn.close();
                }
            }
        }
        if (getLogFilePath) {
            return FGBiz.dspCenter.bankLogsDirPath + File.separator + tmpSubFileName;
        }
        return null;
    }

    public static void writeBankLog(int p_logID, Date p_sTime, Date p_eTime, String prefix, ReqRespHeader p_header, StringBuilder p_sbLog) throws Exception {
        writeBankLog(p_logID, p_sTime, p_eTime, prefix, p_header, p_sbLog, false);
    }

    /**
     * 一小时写一个日志文件
     */
    public static void writeBankLogByHour(Date p_eTime, String prefix, ReqRespHeader p_header, StringBuilder p_sbLog) throws Exception {
        writeBankLogByHour(p_eTime, prefix, p_header, p_sbLog.toString());
    }

    public static void writeBankLogByHour(Date p_eTime, String prefix, ReqRespHeader p_header, String p_Log) throws Exception {
        if (FGBiz.enableAsyncBankLog) {//异步日志
            FGBiz.logTrace.infoNoTimeBank(p_header.bankCode, p_header.transType, p_Log.toString());
        } else {
            String tmpDateDir = Format.DateForLogDay.format(p_eTime).replace("-", File.separator);
            String tmpSubFileName = "";
            String subDir = StringHelper.joinNotEmpty(File.separator, FGBiz.dspCenter.bankLogsFirstDir, tmpDateDir, p_header.bankCode);
            if (StringHelper.isNullOrEmpty(prefix)) {
                tmpSubFileName = subDir + File.separator + p_header.transType + "_" + Format.DateAndHourFormat.format(p_eTime) + ".txt";
            } else {
                tmpSubFileName = subDir + File.separator + p_header.transType + "_" + prefix + "_" + Format.DateAndHourFormat.format(p_eTime) + ".txt";
            }
            String tmpLogFile = FGBiz.dspCenter.bankLogsDirPath + File.separator + tmpSubFileName;
            FileHelper.appendFile(tmpLogFile, p_Log, "gbk");
        }
    }

    public static void writeBankLogByDay(Date p_eTime, String prefix, ReqRespHeader p_header, String p_Log) throws Exception {
        if (FGBiz.enableAsyncBankLog) {//异步日志
            FGBiz.logTrace.infoNoTimeBank(p_header.bankCode, p_header.transType, p_Log.toString());
        } else {
            String tmpDateDir = Format.Date6YearMonth.format(p_eTime).replace("-", File.separator);
            String tmpSubFileName = "";
            String subDir = StringHelper.joinNotEmpty(File.separator, FGBiz.dspCenter.bankLogsFirstDir, tmpDateDir, p_header.bankCode);
            if (StringHelper.isNullOrEmpty(prefix)) {
                tmpSubFileName = subDir + File.separator + p_header.transType + "_" + Format.Date8Format.format(p_eTime) + ".txt";
            } else {
                tmpSubFileName = subDir + File.separator + p_header.transType + "_" + prefix + "_" + Format.Date8Format.format(p_eTime) + ".txt";
            }
            String tmpLogFile = FGBiz.dspCenter.bankLogsDirPath + File.separator + tmpSubFileName;
            FileHelper.appendFile(tmpLogFile, p_Log, "gbk");
        }
    }

    public static String eleBillLogNameRule(ReqRespHeader p_header, String reqSeqIDOrOwnAct) {
        if (StringHelper.isNullOrEmpty(p_header.transType) || !p_header.transType.startsWith("B")) {
            return reqSeqIDOrOwnAct;
        }
        if ("B004".equals(p_header.transType) || "B005".equals(p_header.transType) || "B007".equals(p_header.transType)) {
            //方便电票正面信息，背面信息，追索人查询日志的查找，需要在文件名中引入票据号
            if (StringHelper.hasAnyChar(p_header.billNo)) {
                reqSeqIDOrOwnAct = p_header.billNo + "_";
            }
        } else if ("B010".equals(p_header.transType)) {
            //业务号+(协议)+流水号+时间+随机数
            if (StringHelper.hasAnyChar(p_header.protocolNo)) {
                reqSeqIDOrOwnAct = p_header.protocolNo + "_" + reqSeqIDOrOwnAct;
            }
        } else if ("B006".equals(p_header.transType)) {
            //业务号+(票据号)+流水号+时间+随机数
            if (!p_header.isQryBillApply) {
                reqSeqIDOrOwnAct = p_header.billNo + "_" + reqSeqIDOrOwnAct;
            }
        }
        //电票交易如果银行返回自己的流水号，也需要埋入文件名中
        else if ("B113".equals(p_header.transType)) {
            if (StringHelper.hasAnyChar(p_header.outTransID)) {
                reqSeqIDOrOwnAct = p_header.outTransID + "_";
            }
            reqSeqIDOrOwnAct = p_header.protocolNo + "_" + reqSeqIDOrOwnAct;
        } else if (p_header.transType.startsWith("B1") || "B003".equals(p_header.transType)) {
            if (StringHelper.hasAnyChar(p_header.outTransID)) {
                reqSeqIDOrOwnAct = p_header.outTransID + "_";
            }
            if (StringHelper.hasAnyChar(p_header.billNo)) {
                reqSeqIDOrOwnAct = p_header.billNo + "_" + reqSeqIDOrOwnAct;
            }
        } else if (p_header.transType.startsWith("Bat101")) {
            reqSeqIDOrOwnAct = p_header.psselNum + "_" + reqSeqIDOrOwnAct;
        }
        return reqSeqIDOrOwnAct;
    }
}